-
Notifications
You must be signed in to change notification settings - Fork 35
Add sveltekit cloudflare pages docs #415
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add sveltekit cloudflare pages docs #415
Conversation
WalkthroughA new documentation file was added, providing detailed instructions and code for integrating Kinde authentication into a SvelteKit app on Cloudflare Pages using Cloudflare KV for secure state and token management. The guide includes setup steps, a custom KV and cookie hybrid storage adapter, authentication route handlers, session management, and route protection. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant SvelteKitApp
participant CloudflareKV
participant KindeAuth
User->>SvelteKitApp: Requests /api/auth/login
SvelteKitApp->>CloudflareKV: Store OAuth state (setState)
SvelteKitApp->>User: Redirect to KindeAuth (login)
User->>KindeAuth: Authenticate
KindeAuth->>User: Redirect back with code/state
User->>SvelteKitApp: Requests /api/auth/kinde_callback
SvelteKitApp->>CloudflareKV: Validate state (getState)
SvelteKitApp->>KindeAuth: Exchange code for tokens (with client secret and PKCE)
KindeAuth-->>SvelteKitApp: Return tokens
SvelteKitApp->>CloudflareKV: Store tokens (setState)
SvelteKitApp->>User: Set session cookie and redirect to app
User->>SvelteKitApp: Requests protected route
SvelteKitApp->>CloudflareKV: Check tokens (getState)
alt Tokens expired
SvelteKitApp->>KindeAuth: Refresh tokens
KindeAuth-->>SvelteKitApp: Return refreshed tokens
SvelteKitApp->>CloudflareKV: Update tokens
end
alt Authenticated
SvelteKitApp->>User: Serve protected content
else Not authenticated
SvelteKitApp->>User: Redirect to login
end
Suggested labels
Suggested reviewers
Poem
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🧹 Nitpick comments (12)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (12)
1-5
: Nitpick: Validate front matter schema.
Ensure the YAML front matter keys (page_id
,title
,description
) align with your documentation site's expected schema. Consider adding metadata fields likesidebar_position
orcategory
if your site supports them for better navigation.
8-11
: Suggestion: Use a callout component for complexity note.
Instead of a plain blockquote, leverage your MDX callout/snippet component (e.g.,<Alert type="warning">…</Alert>
) to highlight the implementation complexity. It improves readability and consistency with other guides.
13-18
: Optional: Clarify prerequisites.
Add explicit versions for Node.js, SvelteKit, Wrangler CLI, and specify which Cloudflare Pages target (e.g.,pages
) you’re deploying to. It prevents compatibility issues for newcomers.
31-34
: Combine installation commands.
You can streamline dependency installation into a single command for brevity:- ```bash - npm install @kinde-oss/kinde-auth-sveltekit - npm install -D @sveltejs/adapter-cloudflare - ``` + ```bash + npm install @kinde-oss/kinde-auth-sveltekit @sveltejs/adapter-cloudflare -D + ```
47-65
: Nitpick: Consistent quoting inwrangler.toml
.
You mix single- and double-quotes for environment variables. For clarity and consistency, use double quotes throughout:-[vars] -KINDE_SCOPE = 'openid profile email offline' + [vars] + KINDE_SCOPE = "openid profile email offline"Also consider updating
compatibility_date
to the latest stable date to avoid deprecation warnings.
179-183
: Refactor: Uniform error response.
Bothconsole.error
andreturn json({ error: ... })
are used. Consider extracting a helper for error responses to maintain a consistent JSON shape and status code across all endpoints.
185-201
: Optional: Replaceswitch
with a handler map.
A lookup object reduces boilerplate and makes adding endpoints easier:const handlers: Record<string, Handler> = { login: (e) => handleLogin(e, storage, false), register: (e) => handleLogin(e, storage, true), kinde_callback: (e) => handleCallback(e, storage), logout: (e) => handleLogout(e, storage) }; return handlers[path]?.(event) ?? json({ error: 'Unknown auth endpoint' }, { status: 404 });
214-218
: Nitpick: Move helper functions to a shared utils file.
Extractsha256
andbase64URLEncode
intosrc/lib/utils/crypto.ts
to avoid cluttering the route handler and enable reuse across other guides or modules.
365-443
: Optional: Simplify client_secret logic.
Since Kinde always requires the client secret, you can remove theif (USE_PKCE && …)
branch and always appendclient_secret
, then conditionally appendcode_verifier
. This flattens nested conditions.
445-457
: Optional: Clear session cookies on logout.
After deleting tokens from KV, also clear any session cookies (Set-Cookie: session=; Max-Age=0
) to fully end the user’s session client-side.
459-469
: Optional: Handle circular objects insafeStringify
.
For more robust error logging, consider using a library likefast-safe-stringify
which gracefully handles circular references.
500-520
: Optional: Delegate route protection tosessionHooks
.
Rather than manually checkingstorage.getState('tokens')
, leverage the hook-injectedevent.locals.session
or a helperensureAuthenticated(event)
to reduce duplication and centralize logic.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
(1 hunks)
🔇 Additional comments (2)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (2)
133-146
: Suggestion: VerifysessionHooks
integration.
Confirm thatsessionHooks
actually injects session data intoevent.locals
beforeresolve(event)
. Some hook implementations require you to capture and return its response:// e.g. const response = await sessionHooks({ event, storage }); return await resolve(event, { locals: event.locals });Please double-check the
@kinde-oss/kinde-auth-sveltekit
docs for exact usage.
220-225
: Skip: Base64 URL encoding logic is correct.
This implementation properly replaces URL-unsafe characters. No changes needed.
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (2)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (2)
199-204
: Cryptographically secure randomness is correctly implemented
You’re already usingcrypto.getRandomValues
, which satisfies the earlier recommendation to avoidMath.random()
. No changes needed here.
446-504
: Guard verbose logging behind a debug flag
There are multipleconsole.log
calls printing URLs, statuses, and potentially sensitive data. As noted in previous feedback, avoid verbose or secret-exposing logs in production. Wrap these logs in a debug check (e.g.if (KINDE_DEBUG === 'true') { ... }
).
🧹 Nitpick comments (2)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (2)
56-65
: (Optional) Expose a debug flag in your Wrangler config
You referenceKINDE_DEBUG
in the code but haven’t added it towrangler.toml
. Consider adding:KINDE_DEBUG = "false"This lets users toggle detailed logs without touching source.
532-537
: Enhance cookie security withSecure
attribute
When setting thekinde_session
cookie, add; Secure
so it’s only sent over HTTPS. Example:- 'Set-Cookie': `kinde_session=${sessionId}; Path=/; HttpOnly; SameSite=Lax; Max-Age=2592000` + 'Set-Cookie': `kinde_session=${sessionId}; Path=/; HttpOnly; SameSite=Lax; Secure; Max-Age=2592000`
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
(1 hunks)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🧹 Nitpick comments (10)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (10)
1-5
: Add an explicit H1 heading.
While the frontmatter definestitle
, it’s helpful for readability to include an H1 in the content itself. For example, right after the frontmatter add:# Integrating Kinde Authentication with SvelteKit on Cloudflare Pages
8-11
: Convert the implementation note into an admonition.
To improve scannability, wrap the complexity note in a callout (e.g., a::: tip
or::: warning
block) rather than inline text:::: tip This implementation is more complex than ideal due to Cloudflare's serverless constraints. We're working on more elegant solutions, but this guide provides a robust working implementation. :::
79-81
: Log or surface missing KV binding errors.
createKindeStorage
currently returnsnull
silently whenAUTH_STORAGE
is unavailable. Consider logging or throwing to help readers diagnose misconfigurations:- if (!AUTH_STORAGE) { - return null; - } + if (!AUTH_STORAGE) { + console.error('❌ AUTH_STORAGE KV namespace is not bound in Wrangler'); + return null; + }
84-95
: Avoid swallowing errors in storage adapter.
All catch blocks returnfalse
ornull
without logging the underlying exception. For better debugging, logerror.message
:- } catch (error) { - return false; - } + } catch (error) { + console.error('KV.setState error:', error); + return false; + }Apply similar logging in
getState
anddeleteState
.
360-367
: Add theSecure
attribute to cookies.
When settingkinde_session
, includeSecure;
so browsers only send it over HTTPS:- 'Set-Cookie': `kinde_session=${sessionId}; Path=/; HttpOnly; SameSite=Lax; Max-Age=2592000` + 'Set-Cookie': `kinde_session=${sessionId}; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=2592000`
397-404
: Gate verbose logs behind the debug flag.
fetchTokens
prints URLs and flags on every invocation, which may leak PII. Wrap allconsole.log
calls in:if (KINDE_DEBUG === 'true') { /* ... */ }to mirror other parts of the implementation.
462-466
: Use SvelteKit’sevent.cookies
API.
Instead of manual regex parsing ofevent.request.headers
, prefer:const sessionId = event.cookies.get('kinde_session');This is more robust and future-proof.
507-511
: Remove unusedkindeAuthClient
import.
kindeAuthClient
is imported but never used in this snippet. Deleting it will keep the sample focused:-import { kindeAuthClient } from '@kinde-oss/kinde-auth-sveltekit';
521-524
: Simplify cookie retrieval inload()
.
As above, useevent.cookies.get('kinde_session')
to fetch the session ID instead of regex on headers.
577-584
: Consolidate token refresh logic.
You duplicate an OAuth token-refresh flow here. Consider reusingfetchTokens
(withgrant_type=refresh_token
) or extracting shared logic into a helper to avoid drift.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
(1 hunks)
🔇 Additional comments (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (1)
133-142
: Session hooks integration looks solid.
Thehandle
function properly injects the custom storage adapter when available and defers to default behavior otherwise.
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
Hey @KeeganBeuthin not sure if you are finished with this, but looks like coderabbit has a few suggestions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (1)
154-158
:⚠️ Potential issueMissing import for
KINDE_DEBUG
You’ve added aKINDE_DEBUG
variable in your Wrangler config but are not importing it here. Without it, you cannot guard debug logs. Add to the import:-import { KINDE_ISSUER_URL, KINDE_CLIENT_ID, KINDE_CLIENT_SECRET, KINDE_REDIRECT_URL, KINDE_POST_LOGIN_REDIRECT_URL, KINDE_POST_LOGOUT_REDIRECT_URL, KINDE_AUTH_WITH_PKCE, KINDE_SCOPE } from '$env/static/private'; +import { + KINDE_ISSUER_URL, + KINDE_CLIENT_ID, + KINDE_CLIENT_SECRET, + KINDE_REDIRECT_URL, + KINDE_POST_LOGIN_REDIRECT_URL, + KINDE_POST_LOGOUT_REDIRECT_URL, + KINDE_AUTH_WITH_PKCE, + KINDE_SCOPE, + KINDE_DEBUG +} from '$env/static/private';
🧹 Nitpick comments (5)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (5)
31-34
: Consolidate dependency installation
Instead of two separatenpm install
commands, you can combine them to reduce friction:npm install @kinde-oss/kinde-auth-sveltekit @sveltejs/adapter-cloudflare -D
80-82
: Improve error visibility in the storage adapter
Currently,createKindeStorage
and its methods swallow errors and returnnull
/false
, which can make debugging difficult. Consider logging the caught error or rethrowing so failures are visible during development:- if (!AUTH_STORAGE) { - return null; - } + if (!AUTH_STORAGE) { + console.error('AUTH_STORAGE binding missing'); + throw new Error('KV namespace binding AUTH_STORAGE is not configured.'); + } ... - } catch (error) { - return false; - } + } catch (error) { + console.error('KV put error:', error); + throw error; + }Also applies to: 94-96, 111-113, 121-123
461-464
: Leverage SvelteKit’sevent.cookies
API
Manually parsingevent.request.headers.get('cookie')
is error‐prone. Prefer:const sessionId = event.cookies.get('kinde_session');And to clear:
event.cookies.delete('kinde_session', { path: '/', secure: true, sameSite: 'Lax' });This improves readability and correctness.
Also applies to: 515-518, 615-618
501-502
: Remove unusedkindeAuthClient
import
You importkindeAuthClient
but never use it in+layout.server.ts
. Either use the client for session loading or remove this line to avoid confusion.
603-646
: Extract common cookie and token logic into helpers
The dashboard load logic duplicates cookie parsing andgetUserIdFromToken
. Consider moving these to shared utilities ($lib/session.ts
) and reusing them across both the layout and dashboard handlers to DRY up the code.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
(1 hunks)
🔇 Additional comments (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (1)
1-5
: Frontmatter is well‐formed
The YAML frontmatter includespage_id
,title
, anddescription
, which are essential for MDX metadata.
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (1)
445-467
:⚠️ Potential issueMissing Secure flag on cookie clear
When clearing thekinde_session
cookie, you should include theSecure
attribute to match the setter and ensure the cookie is invalidated over HTTPS:- 'Set-Cookie': 'kinde_session=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0' + 'Set-Cookie': 'kinde_session=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0'This is critical to avoid stale cookies.
🧹 Nitpick comments (10)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (10)
1-5
: Frontmatter formatting
Consider aligning the frontmatter with the MDX style guide. For example, ifpage_id
is auto-generated (and not referenced elsewhere), you can remove it or add a comment explaining its use so readers understand why it’s present.
31-34
: Combine installation commands
You can streamline the setup by installing both packages in one step, e.g.:npm install @kinde-oss/kinde-auth-sveltekit -D @sveltejs/adapter-cloudflareThis reduces friction for readers following the guide.
85-94
: Log storage errors for debugging
Silently returningfalse
insetState
can obscure KV failures. Consider logging the exception before returning:} catch (error) { - return false; + console.error('KV setState error:', error); + return false; }This will help users triage storage issues.
99-110
: Surface KV retrieval errors
Similarly, suppressing errors ingetState
by returningnull
hides root causes. Add logging for the catch block:} catch (error) { - return null; + console.error('KV getState error:', error); + return null; }This improves observability in production.
157-158
: Cleanup environment imports
You’ve definedKINDE_DEBUG
inwrangler.toml
but it’s not imported or used here. Either removeKINDE_DEBUG
from the configuration or import and guard your logs against it (e.g., wrapconsole.error
/console.debug
calls).
169-178
: Robust endpoint detection
url.pathname.split('/').pop()
can return an empty string if the path ends with a slash. Consider trimming trailing slashes first:const path = url.pathname.replace(/\/$/, '').split('/').pop() || '';This ensures you always extract the correct segment.
275-377
: Scope debug/error keys per user
You’re storing callback errors under generic keys ('last_error'
,'token_error'
), which may collide across concurrent flows. Namespace these entries (e.g.,error:state:${state}
or using the session ID) to isolate error data per user.
379-442
: Simplify PKCE branch
Since you only store a truecodeVerifier
when PKCE is enabled, the extra!== 'true'
check is no longer needed. You can streamline to:- if (USE_PKCE && codeVerifier && codeVerifier !== 'true') { - params.append('code_verifier', codeVerifier); - params.append('client_secret', SECRET); - } else { - params.append('client_secret', SECRET); - } + params.append('client_secret', SECRET); + if (USE_PKCE && codeVerifier) { + params.append('code_verifier', codeVerifier); + }This reduces conditional complexity.
501-504
: Use SvelteKit's cookie API
Rather than parsingevent.request.headers
, leverage SvelteKit’s built-in cookie helpers:const sessionId = event.cookies.get('kinde_session');This simplifies the code and handles encoding correctly.
589-632
: Route protection example
The dashboard load function clearly illustrates guarding routes. To avoid duplicate logic, consider exporting and reusing thegetUserIdFromToken
helper from your callback code rather than redefining it here.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
(1 hunks)
🔇 Additional comments (6)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (6)
137-143
: Integrate session hooks with storage
The conditional spread ofstorage
intosessionHooks
is concise and correctly bypasses KV when unbound. This cleanly wires Cloudflare KV into the Kinde session lifecycle.
200-205
: Secure randomness for OAuth state
Great use ofcrypto.getRandomValues
for generating the state parameter—this addresses the cryptographic security concern and was an essential fix.
208-219
: PKCE helper functions
Thesha256
andbase64URLEncode
utilities correctly implement the PKCE code challenge. Their concise, promise-based design is ideal for Cloudflare’s environment.
221-272
: Login flow implementation
The login handler cleanly orchestrates state, redirect, optional PKCE setup, and redirects to Kinde. Parameter extraction was moved into the correct order—this is well structured and readable.
469-480
: Graceful error serialization
ThesafeStringify
helper elegantly handles bothError
objects and unstringifiable payloads, ensuring robust debugging output.
556-582
: Token refresh flow
The refresh logic correctly handles HTTP errors and JSON parsing, storing refreshed tokens back to KV. This aligns neatly with OAuth best practices.
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (12)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (12)
8-11
: Rephrase the note for clarity.
Consider updating “more complex than ideal” to something like “more complex than desired” to make the tone smoother.
13-18
: Specify Node.js and npm versions in prerequisites.
Add a note about required Node.js (e.g., v16+) and npm/yarn versions to ensure compatibility with SvelteKit and Wrangler.
44-65
: Updatecompatibility_date
to the current date.
The example uses"2023-06-28"
, which may be outdated. Suggest replacing with"<YYYY-MM-DD>"
or documenting that this value should match the latest Cloudflare runtime date.
75-130
: Log errors in KV adapter catch blocks for better observability.
Currently, failures insetState
,getState
, anddeleteState
are swallowed (returningfalse
ornull
). Consider loggingerror.message
inside eachcatch
to aid debugging of KV operations.
157-169
: Polish import formatting and include debug flag.
- Add a missing space after the comma in
KINDE_AUTH_WITH_PKCE,KINDE_SCOPE
.- Since
KINDE_DEBUG
is defined inwrangler.toml
, import it here to enable conditional logging later.
172-200
: Use SvelteKit’s route parameters instead ofURL.pathname
.
Leverageevent.params.kindeAuth
(the dynamic[...kindeAuth]
segment) for dispatching tologin
,register
, etc., to avoid brittle string parsing based on URL segments.
225-274
: Check KV write results inhandleLogin
.
storage.setState
returns a boolean—consider verifying it'strue
and handling error cases (e.g., return a 500 response) rather than assuming success.
397-401
: Simplify PKCE check infetchTokens
.
ThecodeVerifier !== 'true'
condition is redundant sincecodeVerifier
is always a string orundefined
. You can streamline to:- if (USE_PKCE && codeVerifier && codeVerifier !== 'true') { + if (USE_PKCE && codeVerifier) {
490-493
: Remove unusedkindeAuthClient
import.
kindeAuthClient
isn’t referenced in this layout loader; you can delete it to clean up the code.
504-507
: Leverageevent.cookies.get()
for cookie retrieval.
Instead of manually parsingevent.request.headers
, use SvelteKit’sevent.cookies.get('kinde_session')
for more robust cookie handling.
592-597
: Use built-in cookie API in dashboard route.
Similar to the layout loader, replace manual header parsing withevent.cookies.get('kinde_session')
to simplify the protected-route sample.
626-634
: Add TypeScript typing forgetUserIdFromToken
.
Define theidToken
parameter as astring
to improve clarity:function getUserIdFromToken(idToken: string): string | null { ... }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
(1 hunks)
🔇 Additional comments (6)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (6)
1-5
: Frontmatter metadata looks good.
The page_id, title, and description are present and follow the project’s conventions.
19-28
: Verify callback URL formatting.
The example uses/api/auth/kinde_callback
; ensure that matches the route in your SvelteKit project (it should align with the[...kindeAuth]
handler path).
31-34
: Dependency installation is correct.
Installing@kinde-oss/kinde-auth-sveltekit
and the Cloudflare adapter covers the essentials.
38-41
: KV namespace setup instructions are clear.
The steps to create and copy the namespace ID in Cloudflare Pages are accurate.
67-70
: Securing the client secret is well addressed.
MovingKINDE_CLIENT_SECRET
into a Wrangler secret aligns with best practices.
137-149
: Hooks integration is correct.
UsingsessionHooks
with a conditional storage binding ensures session support on Cloudflare Pages.
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (2)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (2)
203-208
: Duplicate of previous crypto‐secure randomness suggestion
generateRandomString
now usescrypto.getRandomValues
, fulfilling the earlier recommendation to avoidMath.random()
.
373-378
:⚠️ Potential issueNamespace token exchange errors
You log and store JSONified errors under a fixed keytoken_error
, which could collide across users or flows. It’s safer to namespace it similarly to state errors, e.g.:- await storage.setState('token_error', { … }); + await storage.setState(`token_error:${state}`, { … });
🧹 Nitpick comments (4)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (4)
46-65
: Suggest updatingcompatibility_date
to the current date
Keepingcompatibility_date
up-to-date helps ensure you benefit from the latest Cloudflare Pages runtime improvements. Consider bumping this to today’s date (e.g.,"2025-05-01"
).
75-130
: Improve error visibility in the KV storage adapter
Currently,setState
/getState
/deleteState
swallow errors and returnfalse
/null
without logging. In a production scenario, you’d want to at least logerror.message
(or rethrow) to aid debugging. For example:setState: async (stateId: string, stateData: any) => { try { // ... await AUTH_STORAGE.put(key, value, { expirationTtl: 600 }); return true; } catch (error) { - return false; + console.error(`KV put failed for ${key}:`, error); + throw error; } },
383-445
: Minor: simplify PKCE vs. non-PKCE branch
The checkcodeVerifier && codeVerifier !== 'true'
is vestigial—your stored state is never the literal"true"
. You can consolidate to:- if (USE_PKCE && codeVerifier && codeVerifier !== 'true') { + if (USE_PKCE && codeVerifier) {
490-493
: Remove unused import
kindeAuthClient
is imported but never used in+layout.server.ts
. Consider removing to keep the snippet focused:- import { kindeAuthClient } from '@kinde-oss/kinde-auth-sveltekit';
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
(1 hunks)
🔇 Additional comments (15)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (15)
137-150
: Hooks integration is correctly wired
ThesessionHooks
call now properly passesstorage
only when available, preserving default behavior otherwise. This aligns with the package’s API and looks correct.
157-170
: Environment imports look good
All required KINDE_* vars are pulled from$env/static/private
, andKINDE_DEBUG
isn’t referenced in this example (debug logs have been removed), so you don’t need to import it here.
172-200
: Approve GET handler routing logic
The switch onpath
correctly delegates to the four endpoints (login
,register
,kinde_callback
,logout
) and falls back to a 404. Error handling for missing KV is appropriate.
211-215
: SHA-256 helper implementation is correct
Thesha256
function leveragescrypto.subtle.digest
as expected for PKCE, with proper encoding.
217-222
: Base64 URL‐encode helper is accurate
Yourbase64URLEncode
correctly replaces URL-unsafe characters and trims padding.
225-274
: Login handler properly scopes state and redirect
You generate a cryptographically securestate
, conditionally store the PKCE verifier, and namespace both verifier and redirect keys. The OAuth URL construction is clear and correct.
297-308
: State validation and error scoping look good
Invalid state flows now log the error and store a namespacederror:${state}
entry, avoiding cross-session collisions.
318-321
: Cleanup of state and redirect keys is correct
Deleting both the PKCE verifier and redirect entries ensures no stale data remains in KV.
323-336
: Token storage under session‐scoped key is solid
Storing the full token set withtimestamp
and TTL fields undersession:${sessionId}:tokens
is precisely what you need for later validation and refresh.
340-352
: User ID extraction is handled safely
The ID token is parsed defensively with atry/catch
, which prevents runtime crashes on malformed tokens.
359-367
: Session cookie includesSecure
flag
YourSet-Cookie
header now hasHttpOnly; Secure; SameSite=Lax; Max-Age=2592000
, which aligns with best practices.
448-470
: Logout handler correctly clears session
Deleting thesession:${sessionId}:tokens
key and clearing the cookie withSecure; SameSite=Lax
is spot-on.
473-483
:safeStringify
covers edge cases
This helper gracefully handles errors and unstringifiable objects. It’s concise and effective.
495-557
: Layout load function and token refresh logic are correct
The session lookup, expiration check with buffer, and refresh flow cover all necessary cases. Error handling safely falls back to unauthenticated.
592-635
: Dashboard route protection is solid
You correctly redirect unauthenticated users and extractuserId
from the ID token. In a Cloudflare Pages environment,atob
is available, so this will run smoothly.
resolved a few of the comments that were outdated. |
@@ -0,0 +1,638 @@ | |||
--- | |||
page_id: 4f3a9e2a-12eb-4b4c-8790-48b6e09a224d |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use the following as front matter:
---
page_id: 4f3a9e2a-12eb-4b4c-8790-48b6e09a224d
title: Kinde with Sveltekit on Cloudflare Pages
sidebar:
order: 9
relatedArticles:
- 855e5ca8-f2fb-4162-a594-10cee8a2ff8b
- f1ba22b9-b35f-478a-be09-4524d060fe36
- 00d62179-e0e8-489c-90f7-9a593f3b058a
---
This guide walks you through implementing Kinde authentication in a SvelteKit application deployed to Cloudflare Pages using KV storage for state management. | ||
|
||
|
||
> Note: This implementation is more complex than ideal due to Cloudflare's serverless environment constraints. We're working on more elegant solutions, but this guide provides a robust working implementation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Notes and warnings, etc. are rendered in markdown as:
<Aside type="warning">
This implementation is more complex than ideal due to Cloudflare's serverless environment constraints. We're working on more elegant solutions, but this guide provides a robust working implementation.
</Aside>
|
||
> Note: This implementation is more complex than ideal due to Cloudflare's serverless environment constraints. We're working on more elegant solutions, but this guide provides a robust working implementation. | ||
|
||
## Prerequisites |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename to : What you need
- A Kinde account (register at [kinde.com](https://kinde.com)) | ||
- SvelteKit project ready for Cloudflare Pages deployment | ||
|
||
## 1. Set Up a Kinde Application |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our styling for step headings is 'Step #: Heading' Use colon.
Step 1: Heading
Step 2: Heading
etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Application should be lowercase
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also we use Sentence case, not title case
A few heading fixes and punctuation updates.
KINDE_DEBUG = "false" | ||
``` | ||
|
||
## 4.1 Add KINDE_CLIENT_SECRET Separately from a .dev.vars file to avoid leaking your secret. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't use substep headings. Make this a h3 if it's part of step 4, or else renumber headings to make this 5.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (10)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (10)
13-13
: Rename "Prerequisites" heading to "What you need"
Per style guidelines, the first section should be titled What you need.
152-152
: 🛠️ Refactor suggestionStandardize step heading style
Update to:- ## 7. Implement authentication routes + ## Step 7: Implement authentication routes
587-587
: 🛠️ Refactor suggestionStandardize step heading style
Update to:- ## 9. Protect routes + ## Step 9: Protect routes
132-132
: 🛠️ Refactor suggestionStandardize step heading style
Update to:- ## 6. Set up SvelteKit Hooks + ## Step 6: Set up SvelteKit hooks
36-36
: 🛠️ Refactor suggestionStandardize step heading style
Update to:- ## 3. Configure Cloudflare KV Storage + ## Step 3: Configure Cloudflare KV storage
485-488
: 🛠️ Refactor suggestionStandardize step heading style
Update to:- ## 8. Check Authentication Status + ## Step 8: Check authentication status
71-71
: 🛠️ Refactor suggestionStandardize step heading style
Update to:- ## 5. Create a KV Storage Adapter + ## Step 5: Create a KV storage adapter
11-11
: 🛠️ Refactor suggestionUse
<Aside>
component for warnings
Replace the blockquote note with the<Aside type="warning">
component to ensure it renders consistently with our design system:- > Note: This implementation is more complex than ideal due to Cloudflare's serverless environment constraints. … + <Aside type="warning"> + + This implementation is more complex than ideal due to Cloudflare's serverless environment constraints. … + + </Aside>
19-19
: 🛠️ Refactor suggestionStandardize step headings with "Step #: Heading"
Use our pattern for numbered steps with a colon and sentence case. For example:- ## 1. Set Up a Kinde application + ## Step 1: Set up a Kinde application
1-5
:⚠️ Potential issueComplete front matter for sidebar and related articles
The front matter is missing thesidebar
,order
, andrelatedArticles
fields required by our documentation templates. Please update to match the standard front matter:--- page_id: 4f3a9e2a-12eb-4b4c-8790-48b6e09a224d title: "Integrating Kinde Authentication with SvelteKit on Cloudflare Pages" +sidebar: + order: 9 +relatedArticles: + - 855e5ca8-f2fb-4162-a594-10cee8a2ff8b + - f1ba22b9-b35f-478a-be09-4524d060fe36 + - 00d62179-e0e8-489c-90f7-9a593f3b058a description: "A step-by-step guide to implement Kinde authentication in a SvelteKit application deployed to Cloudflare Pages" ---
🧹 Nitpick comments (8)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (8)
31-34
: Combine installation commands for brevity
You can merge the twonpm install
commands into one for conciseness:```bash -npm install @kinde-oss/kinde-auth-sveltekit -npm install -D @sveltejs/adapter-cloudflare +npm install @kinde-oss/kinde-auth-sveltekit +npm install --save-dev @sveltejs/adapter-cloudflare--- `67-70`: **Consolidate secret instructions under the main Wrangler setup** Rather than a separate "4.1" subheading, consider folding the `wrangler secret put` guidance into Step 4 to keep numbering flat and clear. --- `75-130`: **Improve error handling in the storage adapter** Currently errors are swallowed (returning `false`/`null`) without logging, which can make debugging difficult. Consider logging the error message before returning, or throwing an explicit error to bubble up issues: ```diff setState: async (stateId: string, stateData: any) => { try { … } catch (error) { - return false; + console.error(`createKindeStorage.setState error for ${stateId}:`, error); + return false; } },
154-200
: Format imports and spacing for readability
Split the long import onto multiple lines and ensure spaces after commas:-import { KINDE_ISSUER_URL, KINDE_CLIENT_ID, KINDE_CLIENT_SECRET, KINDE_REDIRECT_URL, KINDE_POST_LOGIN_REDIRECT_URL, KINDE_POST_LOGOUT_REDIRECT_URL, KINDE_AUTH_WITH_PKCE,KINDE_SCOPE } from '$env/static/private'; +import { + KINDE_ISSUER_URL, + KINDE_CLIENT_ID, + KINDE_CLIENT_SECRET, + KINDE_REDIRECT_URL, + KINDE_POST_LOGIN_REDIRECT_URL, + KINDE_POST_LOGOUT_REDIRECT_URL, + KINDE_AUTH_WITH_PKCE, + KINDE_SCOPE +} from '$env/static/private';
224-275
: Add error handling around storage operations
Wrap calls tostorage.setState
intry/catch
or at least check the boolean return value to ensure state or redirect is stored successfully before proceeding.
383-444
: Simplify PKCE verification logic
The checkcodeVerifier !== 'true'
is unnecessary—codeVerifier
is either a generated string orundefined
. Simplify to:- if (USE_PKCE && codeVerifier && codeVerifier !== 'true') { + if (USE_PKCE && codeVerifier) {
490-492
: Remove unusedkindeAuthClient
import
kindeAuthClient
is imported but never used. Consider removing this line to prevent confusion:- import { kindeAuthClient } from '@kinde-oss/kinde-auth-sveltekit';
592-635
: Type and reuse thegetUserIdFromToken
helper
Define the function signature explicitly and consider sharing it between the callback and dashboard logic to avoid duplication. For example:- function getUserIdFromToken(idToken) { + function getUserIdFromToken(idToken: string): string | null {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
(1 hunks)
🔇 Additional comments (4)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (4)
137-150
: Hooks integration snippet looks correct
Thehandle
function properly injects the KV storage adapter intosessionHooks
.
202-209
: Helper functions are correctly implemented
generateRandomString
,sha256
, andbase64URLEncode
use secure APIs and handle encoding/decoding appropriately.
448-470
: Logout handler correctly clears session
The code properly deletes the KV entry and clears the secure session cookie.
472-483
: Error stringification helper is robust
safeStringify
handles bothError
instances and arbitrary objects safely.
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
Hey @KeeganBeuthin I'm not able to do a code check, but from a style/copy perspective I left a few comments. Here's our contribution guide for future topics - https://docs.kinde.com/contribute/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (2)
51-54
: Standardize Step 4 heading style
The heading uses “Set Up” instead of “Set up”. This duplicates an earlier suggestion.
286-389
:⚠️ Potential issueNamespace token_error storage to avoid collisions
Storing errors under a global key risks overlapping diagnostics across flows. Use a state-specific key likeerror:${state}
.- await storage.setState('token_error', { + await storage.setState(`error:${state}`, { time: new Date().toISOString(), error: safeStringify(error) });
🧹 Nitpick comments (5)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (5)
28-37
: Use sentence case for step headings
The step title uses “Set Up” (title case). To align with Sentence case guidelines, change to “Set up”.- ## Step 1: Set Up a Kinde application + ## Step 1: Set up a Kinde application
45-50
: Sentence case for Storage step
Change “Configure Cloudflare KV Storage” to “Configure Cloudflare KV storage” to match Sentence case conventions.- ## Step 3: Configure Cloudflare KV Storage + ## Step 3: Configure Cloudflare KV storage
56-74
: Consider updating compatibility_date
Thecompatibility_date = "2023-06-28"
is outdated for a 2025 deployment. Updating this to a more recent date ensures alignment with Cloudflare Pages’ current environment.- compatibility_date = "2023-06-28" + compatibility_date = "2025-05-01" # or the current date of merge
84-139
: Enhance storage adapter error visibility
Silentreturn false
/null
in catch blocks can obscure underlying issues. Logging the error message will aid debugging.} catch (error) { - return false; + console.error('KV setState error:', error); + return false; } ... } catch (error) { - return null; + console.error('KV getState error:', error); + return null; } ... } catch (error) { - return false; + console.error('KV deleteState error:', error); + return false; }
392-450
: Clean up unnecessarycodeVerifier
check
Since you only store a verifier when PKCE is enabled, the&& codeVerifier !== 'true'
guard is redundant. Remove it for clarity.- if (USE_PKCE && codeVerifier && codeVerifier !== 'true') { + if (USE_PKCE && codeVerifier) {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
(1 hunks)
🔇 Additional comments (14)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (14)
1-10
: Front matter is correctly formatted
The YAML front matter matches the project’s required keys and indentation style.
16-20
: Admonition formatting looks good
The<Aside type="warning">
block has the proper blank lines before and after content, matching the project’s style.
22-27
: Checklist section is clear
The “## What you need” heading and its bullet list correctly outline prerequisites.
40-43
: Installation instructions are accurate
The npm install commands are clear and correct for both production and dev dependencies.
143-159
: Hook integration is correct
Thehandle
implementation ties Kinde session hooks to the custom storage adapter as intended.
165-209
: Auth route dispatcher looks solid
The switch on the trailing path segment and early storage availability check handle the OAuth flows as expected.
211-217
: Secure random generation is implemented properly
ThegenerateRandomString
function usescrypto.getRandomValues
and a suitable character set.
220-230
: PKCE helper functions are well-defined
Thesha256
andbase64URLEncode
implementations follow the PKCE spec and use the Web Crypto API.
234-284
: Login handler logic is clear and robust
State, PKCE, and redirect parameter handling appear correct, with clean separation of concerns.
456-479
: Logout handler properly clears session
The session cookie is securely cleared with theSecure
flag, and the redirect to Kinde’s logout endpoint is correct.
481-492
: Error stringification helper is effective
ThesafeStringify
function cleanly handles both Error instances and arbitrary objects.
499-567
: Layout load implements token refresh logic correctly
Your logic for reading the session cookie, checking expiry, and refreshing tokens is sound and includes a safety buffer.
569-593
: Refresh token flow is well-handled
The refresh request parameters, error handling, and response parsing cover expected failure modes.
601-644
: Protected route enforcement is correct
The dashboard loader enforces authentication, redirects unauthenticated users, and extracts the user ID safely.
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (1)
381-386
:⚠️ Potential issueNamespace token-error storage to avoid collisions
You’re writing errors under the fixed keytoken_error
, which can overwrite errors from concurrent sessions. Prefix it with the flow’s state or session ID—e.g.,error:${state}
—to isolate per-flow diagnostics.- await storage.setState('token_error', { + await storage.setState(`error:${state}`, {
🧹 Nitpick comments (9)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (9)
1-4
: Capitalize "SvelteKit" correctly in the title
The front-matter title uses "Sveltekit" (lowercase K). For consistency with the product name, update it to "SvelteKit".--- title: Kinde with Sveltekit on Cloudflare Pages +++ title: Kinde with SvelteKit on Cloudflare Pages
28-28
: Ensure consistent sentence-case in step headings
The first step heading uses "Set Up" (title case) while others use sentence case. Change to "Set up a Kinde application" to match style.- ## Step 1: Set Up a Kinde application + ## Step 1: Set up a Kinde application
52-52
: Ensure consistent sentence-case in step headings
Similarly, update "Set Up Wrangler configuration" to "Set up Wrangler configuration" for consistency.- ## Step 4: Set Up Wrangler configuration + ## Step 4: Set up Wrangler configuration
76-79
: Avoid using a sub-heading for a single note
The line "### Add KINDE_CLIENT_SECRET separately…" is rendered as a tertiary heading. Per style, convert this into a regular paragraph or wrap in an<Aside>
block so it doesn’t interrupt the step flow.
56-63
: Refresh compatibility_date to latest Cloudflare environment
The example uses"2023-06-28"
. It’s best practice to bump this to the current date (e.g.,"2025-05-01"
) so readers know it’s tested against the latest Pages runtime.- compatibility_date = "2023-06-28" + compatibility_date = "2025-05-01"
40-43
: Combine installation commands for brevity
You can merge the twonpm install
commands into one to streamline the instructions.npm install @kinde-oss/kinde-auth-sveltekit @sveltejs/adapter-cloudflare --save-dev
87-94
: Handle missing KV binding more explicitly
CurrentlycreateKindeStorage
returnsnull
ifAUTH_STORAGE
isn’t bound—this may lead to silent failures downstream. Consider throwing an error or logging a warning so implementers know their binding is misconfigured.- if (!AUTH_STORAGE) { - return null; - } + if (!AUTH_STORAGE) { + console.error('AUTH_STORAGE namespace is not bound in wrangler.toml'); + throw new Error('Missing KV binding: AUTH_STORAGE'); + }
183-185
: Use SvelteKit’s route params instead of manual URL splitting
Parsing the endpoint byurl.pathname.split('/').pop()
can break if the path changes. Since this is in a[...kindeAuth]
route, you can access the segment viaevent.params.kindeAuth
.- const path = url.pathname.split('/').pop() || ''; + const path = event.params.kindeAuth;
459-462
: Use SvelteKit’s cookie API in logout handler
Instead of parsingevent.request.headers.get('cookie')
, leverageevent.cookies.get('kinde_session')
andevent.cookies.delete('kinde_session')
for clarity and maintainability.- const cookies = event.request.headers.get('cookie') || ''; - const sessionMatch = cookies.match(/kinde_session=([^;]+)/); - const sessionId = sessionMatch ? sessionMatch[1] : null; + const sessionId = event.cookies.get('kinde_session'); + if (sessionId) { + event.cookies.delete('kinde_session', { path: '/', httpOnly: true, sameSite: 'Lax', secure: true }); + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
(1 hunks)
Hi @KeeganBeuthin As you alluded to there is quite a bit of code here, many of the method and functions here and the flows are included in the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs better utilisaton of @kinde/js-utils
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (2)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (2)
154-156
: Global storage assignment can race across concurrent requests
setActiveStorage
stores the KV instance in a module-level singleton. On Cloudflare Workers, multiple requests share the same isolate, so a second request can overwrite the storage while the first is still executing. Consider returning the storage object frominitializeKindeAuth
and passing it explicitly tojs-utils
functions that allow it, or open an issue to add per-request context support in@kinde/js-utils
.
24-28
: Minor grammar: plural noun without article“A Cloudflare account with Pages and KV access” reads smoother as:
- A Cloudflare account with Pages and KV access + A Cloudflare account with access to Pages and KVPurely editorial – ignore if house style differs.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
(1 hunks)
🧰 Additional context used
🪛 LanguageTool
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
[grammar] ~26-~26: The verb form ‘access’ does not seem to match the subject ‘KV’.
Context: ... A Cloudflare account with Pages and KV access - A Kinde account with an SPA applicati...
(SUBJECT_VERB_AGREEMENT)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
Outdated
Show resolved
Hide resolved
changes made to utilize js-utils. Documentation is reliant on pending approval of kinde-oss/js-utils#142 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (3)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx (3)
24-29
: Minor copy-editing for prerequisites list
The first list item reads “Pages and KV access”. For subject/verb agreement and clarity consider:- A Cloudflare account with Pages and KV access + A Cloudflare account with access to Cloudflare Pages and KVTiny polish, but it prevents the “KV access” grammar warning flagged by tooling.
39-42
: Add missing article in step description
“In Cloudflare dashboard” should include the article “the” to read naturally:- In Cloudflare dashboard, go to **Workers & Pages > KV** + In the Cloudflare dashboard, go to **Workers & Pages > KV**
48-52
: Updatecompatibility_date
to avoid unexpected runtime differences
compatibility_date = "2023-06-28"
is quite old. New contributors copying this file may hit subtle runtime differences (e.g. URL pattern handling) because Workers activates backwards-compat shims for that date. Unless you rely on legacy behaviour, bump this to today’s date or add a note explaining the freeze.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
(1 hunks)
🧰 Additional context used
🪛 LanguageTool
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
[grammar] ~26-~26: The verb form ‘access’ does not seem to match the subject ‘KV’.
Context: ... A Cloudflare account with Pages and KV access - A Kinde account with an SPA applicati...
(SUBJECT_VERB_AGREEMENT)
[uncategorized] ~39-~39: You might be missing the article “the” here.
Context: ... Configure Cloudflare KV storage 1. In Cloudflare dashboard, go to **Workers & Pages > KV...
(AI_EN_LECTOR_MISSING_DETERMINER_THE)
[uncategorized] ~74-~74: You might be missing the article “a” here.
Context: ...DE_CLIENT_SECRET ``` ## Step 4: Create hybrid storage adapter Create `src/lib/kindeA...
(AI_EN_LECTOR_MISSING_DETERMINER_A)
// Handle expected window error in server environment | ||
if (error instanceof Error && error.message.includes('window')) { | ||
// Wait for async token storage to complete | ||
await new Promise(resolve => setTimeout(resolve, 2000)); | ||
return redirect(302, config.postLoginRedirectURL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Replace arbitrary 2 s sleep with deterministic wait
Using setTimeout(2000)
to “wait for async token storage” is brittle: slow writes may still race; fast writes waste 2 s. Prefer awaiting the promise returned by exchangeAuthCode
(it already resolves after storage) or expose a flush()
helper from your storage adapter.
- await new Promise(resolve => setTimeout(resolve, 2000));
+ // Storage write completed inside exchangeAuthCode; no need to delay.
If @kinde/js-utils
truly emits the window error before the promise settles, consider opening an issue upstream instead of hard-coding a delay.
🤖 Prompt for AI Agents
In
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
around lines 266 to 270, replace the arbitrary 2-second setTimeout delay used to
wait for async token storage with a deterministic wait by awaiting the promise
returned by the async token storage function (such as exchangeAuthCode) or by
calling a flush() method from the storage adapter if available. This ensures the
code only proceeds after token storage completes, avoiding brittle fixed delays.
async function handleLogout(config: ReturnType<typeof getConfig>) { | ||
const logoutUrl = new URL('/logout', config.issuerURL); | ||
logoutUrl.searchParams.append('redirect', config.postLogoutRedirectURL); | ||
|
||
return redirect(302, logoutUrl.toString()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logout endpoint doesn’t clear local session data
Redirecting to Kinde’s /logout
without first deleting session cookies or KV tokens means the user can still appear authenticated until the IdP callback returns. Clear both stores before redirecting:
async function handleLogout(config: ReturnType<typeof getConfig>) {
+ // Clear local auth
+ await setActiveStorage().removeSession(); // pseudo-code – adjust to actual js-utils API
+
const logoutUrl = new URL('/logout', config.issuerURL);
logoutUrl.searchParams.append('redirect', config.postLogoutRedirectURL);
return redirect(302, logoutUrl.toString());
}
This ensures instant sign-out and avoids token reuse in subsequent requests.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
async function handleLogout(config: ReturnType<typeof getConfig>) { | |
const logoutUrl = new URL('/logout', config.issuerURL); | |
logoutUrl.searchParams.append('redirect', config.postLogoutRedirectURL); | |
return redirect(302, logoutUrl.toString()); | |
} | |
async function handleLogout(config: ReturnType<typeof getConfig>) { | |
// Clear local auth | |
await setActiveStorage().removeSession(); // pseudo-code – adjust to actual js-utils API | |
const logoutUrl = new URL('/logout', config.issuerURL); | |
logoutUrl.searchParams.append('redirect', config.postLogoutRedirectURL); | |
return redirect(302, logoutUrl.toString()); | |
} |
🤖 Prompt for AI Agents
In
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
around lines 278 to 283, the logout function redirects to the logout URL without
clearing local session data, which can cause the user to appear authenticated
temporarily. Modify the function to clear session cookies and any KV tokens or
local storage related to authentication before performing the redirect. This
ensures immediate sign-out and prevents token reuse in subsequent requests.
export function initializeKindeAuth(event: RequestEvent): boolean { | ||
const platform = event.platform as any; | ||
const env = platform?.env; | ||
const AUTH_STORAGE = env?.AUTH_STORAGE; | ||
|
||
if (!AUTH_STORAGE) { | ||
console.error('KV storage not available'); | ||
return false; | ||
} | ||
|
||
// KV storage for long-term token storage | ||
const tokenStorage = new KvStorage(AUTH_STORAGE, { defaultTtl: 2592000 }); | ||
|
||
// Cookie storage for temporary OAuth data | ||
const tempStorage = new CookieStorage(event); | ||
|
||
// Set up js-utils storage | ||
setActiveStorage(tokenStorage); // For tokens | ||
setInsecureStorage(tempStorage); // For OAuth temp data | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid re-registering global storage on every request
setActiveStorage
and setInsecureStorage
mutate singleton state inside @kinde/js-utils
. Calling them on every request can introduce race conditions under high concurrency and unnecessary object churn.
Suggested pattern:
-let tokenStorage: KvStorage | undefined;
-let tempStorage: CookieStorage | undefined;
-
-export function initializeKindeAuth(event: RequestEvent): boolean {
- …
- // KV storage for long-term token storage
- tokenStorage = tokenStorage ?? new KvStorage(AUTH_STORAGE, { defaultTtl: 2592000 });
- // Cookie storage for temporary OAuth data
- tempStorage = new CookieStorage(event);
- setActiveStorage(tokenStorage);
- setInsecureStorage(tempStorage);
- …
-}
+const globalTokenStorage = new WeakMap<object, KvStorage>();
+
+export function initializeKindeAuth(event: RequestEvent): boolean {
+ …
+ if (!globalTokenStorage.has(AUTH_STORAGE)) {
+ globalTokenStorage.set(AUTH_STORAGE, new KvStorage(AUTH_STORAGE, { defaultTtl: 2592000 }));
+ setActiveStorage(globalTokenStorage.get(AUTH_STORAGE)!);
+ }
+ setInsecureStorage(new CookieStorage(event)); // per-request, fine
+ …
+}
That ensures the heavy KV instance is initialised once per process while keeping per-request cookie storage.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
src/content/docs/integrate/third-party-tools/kinde-sveltekit-with-cloudflare.mdx
around lines 138 to 157, the calls to setActiveStorage and setInsecureStorage
are made on every request, which can cause race conditions and unnecessary
object creation. Refactor the code to initialize the KV storage and call
setActiveStorage once per process outside the request handler, while keeping the
CookieStorage and setInsecureStorage calls inside the request handler to
maintain per-request state. This avoids re-registering global storage on every
request and improves concurrency safety.
This PR adds documentation for integrating Kinde authentication with SvelteKit on Cloudflare Pages.
I've created this guide based on my implementation experience, and while it's functional, I recognize that it's more complex than ideal. The current solution requires more code than I'd like, especially in the server handler, due to the unique constraints of Cloudflare's serverless environment and how it interacts with OAuth flows.
I would greatly appreciate feedback on:
I'm very open to suggestions on how to make this guide more concise and maintainable.
Summary by CodeRabbit